package com.weasel.security.infrastructure.helper;

import java.awt.Color;
import java.awt.Font;
import java.util.List;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import nl.captcha.Captcha;
import nl.captcha.servlet.CaptchaServletUtil;
import nl.captcha.text.renderer.DefaultWordRenderer;
import nl.captcha.text.renderer.WordRenderer;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.weasel.lang.helper.DemonPredict;
import com.weasel.security.infrastructure.exception.InvalidCaptchaException;
import com.google.common.collect.ImmutableList;

/**
 * @author Dylan
 * @mail pickear@gmail.com
 * @time 2014年4月9日
 */
public final class HttpCaptchaHelper {

	private final static Logger log = LoggerFactory.getLogger(HttpCaptchaHelper.class);

	private final static String CAPTCHA_PARAM = "captcha";
	
	private final static List<Font> FOUNTS = ImmutableList.of(
			  												  new Font("Courier New", Font.ITALIC, 40), 
			  												  new Font("Arial", Font.ITALIC, 40),
			  												  new Font("Times New Roman", Font.ITALIC, 40),
			  												  new Font("Verdana", Font.ITALIC, 40)
			 												 );

	private final static List<Color> COLORS = ImmutableList.of(Color.black);

	private final static WordRenderer RENDERER = new DefaultWordRenderer(COLORS, FOUNTS);
	
	private HttpCaptchaHelper() {}

	/**store captcha to session
	 * @param captcha
	 * @param session
	 */
	public static void storeCaptcha(Captcha captcha, HttpSession session) {

		DemonPredict.notNull(session, new InvalidCaptchaException("can not get session"));
		DemonPredict.notNull(captcha, new InvalidCaptchaException(String.format("no captcha in session 【%s】", session.getId())));
		
		synchronized (session) {
			if(log.isTraceEnabled()){
				log.trace(String.format("store captcha to session 【%s】", session.getId()));
			}
			session.setAttribute(CAPTCHA_PARAM, captcha);
		}
	}
	
	/**check captcha
	 * @param captchaCode
	 * @param session
	 */
	public static void checkCaptcha(String captchaCode,HttpSession session){
		
		if(StringUtils.isBlank(captchaCode)){
			throw new InvalidCaptchaException("captcha is blank");
		}
		
		DemonPredict.notNull(session, new InvalidCaptchaException("can not get session"));
		
		Captcha captcha = (Captcha)session.getAttribute(CAPTCHA_PARAM);
		
		DemonPredict.notNull(captcha, new InvalidCaptchaException(String.format("no captcha in session 【%s】", session.getId())));
		
		DemonPredict.isTrue(captcha.isCorrect(captchaCode), new InvalidCaptchaException(String.format("the captcha is %s ,but user input %s",captcha.getAnswer(),captchaCode)));
	
		synchronized (captcha) {
			if(log.isTraceEnabled()){
				log.trace("remove captcha from session");
			}
			session.removeAttribute(CAPTCHA_PARAM);
		}
		
	}
	
	/**
	 * @return
	 */
	public static Captcha createCaptcha(){
		Captcha captcha = new Captcha.Builder(120, 40).addText(RENDERER).addNoise().build();
		return captcha;
	}
	
	/**
	 * @param response
	 * @param session
	 */
	public static void writeAndStoreCaptcha(HttpServletResponse response, HttpSession session){
		Captcha captcha = createCaptcha();
		CaptchaServletUtil.writeImage(response, captcha.getImage());
		storeCaptcha(captcha,session);
	}
	
}
